#include <types.h>
#include <string.h>
#include <iobuf.h>
#include <error.h>
#include <assert.h>
#include <mod.h>

struct iobuf *iobuf_init(struct iobuf *iob, void *base, size_t len,
			 off_t offset)
{
	iob->io_base = base;
	iob->io_offset = offset;
	iob->io_len = iob->io_resid = len;
	return iob;
}

EXPORT_SYMBOL(iobuf_init);

int
iobuf_move(struct iobuf *iob, void *data, size_t len, bool m2b,
	   size_t * copiedp)
{
	size_t alen;
	if ((alen = iob->io_resid) > len) {
		alen = len;
	}
	if (alen > 0) {
		void *src = iob->io_base, *dst = data;
		if (m2b) {
			void *tmp = src;
			src = dst, dst = tmp;
		}
		memmove(dst, src, alen);
		iobuf_skip(iob, alen), len -= alen;
	}
	if (copiedp != NULL) {
		*copiedp = alen;
	}
	return (len == 0) ? 0 : -E_NO_MEM;
}

EXPORT_SYMBOL(iobuf_move);

int iobuf_move_zeros(struct iobuf *iob, size_t len, size_t * copiedp)
{
	size_t alen;
	if ((alen = iob->io_resid) > len) {
		alen = len;
	}
	if (alen > 0) {
		memset(iob->io_base, 0, alen);
		iobuf_skip(iob, alen), len -= alen;
	}
	if (copiedp != NULL) {
		*copiedp = alen;
	}
	return (len == 0) ? 0 : -E_NO_MEM;
}

EXPORT_SYMBOL(iobuf_move_zeros);

void iobuf_skip(struct iobuf *iob, size_t n)
{
	assert(iob->io_resid >= n);
	iob->io_base += n, iob->io_offset += n, iob->io_resid -= n;
}

EXPORT_SYMBOL(iobuf_skip);
